package com.zenithmind.article.pojo.domain;

import com.zenithmind.common.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Min;

/**
 * 文章聚合根
 * 遵循单一职责原则：专注于文章核心业务逻辑
 * 遵循封装原则：通过方法控制状态变更
 * 遵循开闭原则：通过枚举和策略模式支持扩展
 */
@EqualsAndHashCode(callSuper = true)
@Getter
@NoArgsConstructor
@Schema(name = "文章实体", description = "文章聚合根")
public class Article extends BaseEntity {

    @NotBlank(message = "文章标题不能为空")
    @Size(max = 200, message = "文章标题长度不能超过200个字符")
    @Schema(description = "文章标题")
    private String title;

    @NotBlank(message = "文章内容不能为空")
    @Schema(description = "文章内容")
    private String content;

    @Size(max = 500, message = "文章摘要长度不能超过500个字符")
    @Schema(description = "文章摘要")
    private String summary;

    @Schema(description = "封面图片URL")
    private String coverImage;

    @NotBlank(message = "分类ID不能为空")
    @Schema(description = "分类ID")
    private String categoryId;

    @NotBlank(message = "作者ID不能为空")
    @Schema(description = "作者ID")
    private String userId;

    @Min(value = 0, message = "浏览量不能为负数")
    @Schema(description = "浏览量")
    private Integer viewCount = 0;

    @Min(value = 0, message = "点赞数不能为负数")
    @Schema(description = "点赞数")
    private Integer likeCount = 0;

    @Min(value = 0, message = "评论数不能为负数")
    @Schema(description = "评论数")
    private Integer commentCount = 0;

    @Schema(description = "文章状态")
    private ArticleStatus status = ArticleStatus.DRAFT;

    @Schema(description = "是否置顶")
    private Boolean isTop = false;

    @Schema(description = "是否推荐")
    private Boolean isRecommend = false;

    /**
     * 文章状态枚举
     * 遵循开闭原则：新增状态无需修改现有代码
     */
    public enum ArticleStatus {
        DRAFT(0, "草稿"),
        PUBLISHED(1, "已发布"),
        DELETED(2, "已删除"),
        ARCHIVED(3, "已归档");

        private final Integer code;
        private final String description;

        ArticleStatus(Integer code, String description) {
            this.code = code;
            this.description = description;
        }

        public Integer getCode() {
            return code;
        }

        public String getDescription() {
            return description;
        }

        public static ArticleStatus fromCode(Integer code) {
            if (code == null) return DRAFT;
            for (ArticleStatus status : values()) {
                if (status.code.equals(code)) {
                    return status;
                }
            }
            return DRAFT;
        }
    }

    // === 构造方法 ===

    /**
     * 创建新文章
     * 遵循单一职责原则：专门用于创建文章
     */
    public Article(String title, String content, String summary, String categoryId, String userId) {
        this.title = title;
        this.content = content;
        this.summary = summary;
        this.categoryId = categoryId;
        this.userId = userId;
        this.viewCount = 0;
        this.likeCount = 0;
        this.commentCount = 0;
        this.status = ArticleStatus.DRAFT;
        this.isTop = false;
        this.isRecommend = false;
    }

    // === 业务方法 ===

    /**
     * 发布文章
     * 遵循封装原则：通过方法控制状态变更
     */
    public void publish() {
        if (this.status == ArticleStatus.DELETED) {
            throw new IllegalStateException("已删除的文章不能发布");
        }
        this.status = ArticleStatus.PUBLISHED;
    }

    /**
     * 撤回文章到草稿状态
     */
    public void unpublish() {
        if (this.status == ArticleStatus.DELETED) {
            throw new IllegalStateException("已删除的文章不能撤回");
        }
        this.status = ArticleStatus.DRAFT;
    }

    /**
     * 删除文章
     */
    public void delete() {
        this.status = ArticleStatus.DELETED;
    }

    /**
     * 归档文章
     */
    public void archive() {
        if (this.status != ArticleStatus.PUBLISHED) {
            throw new IllegalStateException("只有已发布的文章才能归档");
        }
        this.status = ArticleStatus.ARCHIVED;
    }

    /**
     * 设置置顶
     */
    public void setTop(boolean isTop) {
        this.isTop = isTop;
    }

    /**
     * 设置推荐
     */
    public void setRecommend(boolean isRecommend) {
        this.isRecommend = isRecommend;
    }

    /**
     * 增加浏览量
     */
    public void incrementViewCount() {
        this.viewCount++;
    }

    /**
     * 增加点赞数
     */
    public void incrementLikeCount() {
        this.likeCount++;
    }

    /**
     * 减少点赞数
     */
    public void decrementLikeCount() {
        if (this.likeCount > 0) {
            this.likeCount--;
        }
    }

    /**
     * 增加评论数
     */
    public void incrementCommentCount() {
        this.commentCount++;
    }

    /**
     * 减少评论数
     */
    public void decrementCommentCount() {
        if (this.commentCount > 0) {
            this.commentCount--;
        }
    }

    /**
     * 更新文章内容
     */
    public void updateContent(String title, String content, String summary, String coverImage) {
        if (this.status == ArticleStatus.DELETED) {
            throw new IllegalStateException("已删除的文章不能修改");
        }
        this.title = title;
        this.content = content;
        this.summary = summary;
        this.coverImage = coverImage;
    }

    /**
     * 检查文章是否可以编辑
     */
    public boolean isEditable() {
        return this.status != ArticleStatus.DELETED;
    }

    /**
     * 检查文章是否已发布
     */
    public boolean isPublished() {
        return this.status == ArticleStatus.PUBLISHED;
    }

    /**
     * 检查文章是否为草稿
     */
    public boolean isDraft() {
        return this.status == ArticleStatus.DRAFT;
    }

    /**
     * 获取状态码（用于数据库存储）
     */
    public Integer getStatusCode() {
        return this.status.getCode();
    }

    /**
     * 设置状态（用于数据库读取）
     */
    public void setStatusCode(Integer statusCode) {
        this.status = ArticleStatus.fromCode(statusCode);
    }

    /**
     * 更新文章分类
     */
    public void updateCategory(String categoryId) {
        this.categoryId = categoryId;
    }

    /**
     * 更新点赞数
     */
    public void updateLikeCount(int likeCount) {
        this.likeCount = Math.max(0, likeCount);
    }
}
